#pragma once
#include "PPObject.h"

#define PPLC_FACTORY_MAX_OBJECTS		32768
/* Maximum number of objects that is allowed to occupy a single factory's memory space. */

#define PPLC_CLASS_OBJECT_FACTORY		0x0010

class PPObjectFactory :
	public PPObject
{
	/**
	 * The PPObjectFactory class is responsible for creating new objects from a
	 * predefined set. Each module in PenguinPLC contains at least one
	 * object factory with a specific range of class IDs it can create.
	 */
public:
	PPObjectFactory(void);

	virtual int Create();
	/**
	 *	Each PPObject should override the Create method, so proper initalization is
	 *	performed when the object is loaded at run time.
	 */
	
	virtual int EnumerateObjects(unsigned int * piObjectCount, unsigned int ** ppiClassIDs);
	/**
	 *	Returns a list of all available class IDs this factory is able to create.
	 */

	virtual int CreateObject(unsigned int iClassID, unsigned int * piInstanceID, void ** ppObject);
	/**
	 *	Create an object with a given class ID. If the class ID is unavailable, the method will
	 *	return with an error. If the class can be created, the factory will do so and return
	 *	the proper instance ID as well as a pointer to the object.
	 *
	 *	The object factory will keep track of which objects are created by it, and it will automatically
	 *	destroy any objects it created when the factory itself is destroyed. This will typically happen
	 *	during a module unload.
	 */

	virtual int CreateObject(unsigned int * piInstanceID, void ** ppObject);
	/**
	 *	Create a default object when no class ID is specified. This behavior is not required,
	 *	but useful for module programmers who only want to implement a single class in their
	 *	module and don't want to worry about comparing class IDs.
	 */

	virtual int DestroyObject(PPObject * pObject);
	/**
	 *	Destroy an object that was created by this factory previously. If the object
	 *	does not belong to this factory, the method will throw an error.
	 */

	virtual int Destroy();
	/**
	 *	During the factory destruction, it will query the status of all associated objects
	 *	and subsequently destroy them in reverse order of creation. This will free any
	 *	memory that was in the module's space and prevent invalid references or memory leaks.
	 *
	 *	If one of the objects in the factory's memory space is still in use, destruction will fail.
	 */

	virtual ~PPObjectFactory(void);

protected:

	int iObjectCount;
	unsigned int * puObjectInstances;
	unsigned int * puObjectClasses;
	unsigned PPObject * pObjectCollection;
};
